﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using BidFunLib.DAO;
using BidFunLib.Entity;
using NHibernate;

namespace BidFunLib.Services
{
    /// <summary>
    /// 
    /// </summary>
    public class StatsBidObjectGlobalManager
    {

        private static readonly ILog log = LogManager.GetLogger(typeof(StatsBidObjectGlobalManager));

        /// <summary>
        /// The dao of this manager
        /// </summary>
        private StatsBidObjectGlobalDAO dao = new StatsBidObjectGlobalDAO();

        
        /// <summary>
        /// Singleton instance
        /// </summary>
        private static StatsBidObjectGlobalManager instance;

        /// <summary>
        /// Retreive singleton of this class
        /// </summary>
        public static StatsBidObjectGlobalManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new StatsBidObjectGlobalManager();
                }
                return StatsBidObjectGlobalManager.instance;
            }
            set
            {
                StatsBidObjectGlobalManager.instance = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private StatsBidObjectGlobalManager()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="statsBidSaleList"></param>
        public void calculateStatsBidObjectGlobal(StatsBidSale statsBidSale) 
        {
            log.Info("calculateStatsBidObjectGlobal");
            if (statsBidSale != null)
            {
                StatsBidObjectGlobal statsBidObjectGlobal = dao.getStatsBidObjectGlobalByIdObject(statsBidSale.IdBidObject);

                if (statsBidObjectGlobal == null)
                {
                    log.Info("statsBidObjectGlobal don't exist in db => we create it in db.");
                    statsBidObjectGlobal = new StatsBidObjectGlobal();
                    statsBidObjectGlobal.IdStatsBidObjectGlobal = -1;
                    statsBidObjectGlobal.IdBidObject = statsBidSale.IdBidObject;
                    statsBidObjectGlobal.MinFinalAmount = 10000000;
                    statsBidObjectGlobal.MinMeanPointsPaidByUsers = 10000000;
                    statsBidObjectGlobal.MinNbBidsByBot = 10000000;
                    statsBidObjectGlobal.MinNbBidsManual = 10000000;
                    statsBidObjectGlobal.MinNbUsersConnected = 10000000;
                    statsBidObjectGlobal.MinNbUsersLogsOnThisObject = 10000000;
                    statsBidObjectGlobal.MinSaleDurationInSeconds = 10000000;
                    statsBidObjectGlobal.MinWinnerNbPointsPaid = 10000000;
                    statsBidObjectGlobal.MinWinnerPsychologicRatio = 10000000;
                }
                else
                {
                    log.Info("statsBidUserByBidObject exist in db => we just update it with new values.");
                }

                statsBidObjectGlobal.RealPrice = statsBidSale.RealPrice;

                // Final Amount Min Mean Max
                if (statsBidObjectGlobal.MinFinalAmount > statsBidSale.Amount)
                {
                    statsBidObjectGlobal.MinFinalAmount = statsBidSale.Amount;
                }
                if (statsBidObjectGlobal.MaxFinalAmount < statsBidSale.Amount)
                {
                    statsBidObjectGlobal.MaxFinalAmount = statsBidSale.Amount;
                }
                Double totalMeanFinalAmount = statsBidObjectGlobal.MeanFinalAmount * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanFinalAmount = (totalMeanFinalAmount + statsBidSale.Amount) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max PointsPaidByUsers
                if (statsBidObjectGlobal.MinMeanPointsPaidByUsers > statsBidSale.MeanPointsPaidByUsers)
                {
                    statsBidObjectGlobal.MinMeanPointsPaidByUsers = statsBidSale.MeanPointsPaidByUsers;
                }
                if (statsBidObjectGlobal.MaxMeanPointsPaidByUsers < statsBidSale.MeanPointsPaidByUsers)
                {
                    statsBidObjectGlobal.MaxMeanPointsPaidByUsers = statsBidSale.MeanPointsPaidByUsers;
                }
                Double totalMeanMeanPointsPaidByUsers = statsBidObjectGlobal.MeanMeanPointsPaidByUsers * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanMeanPointsPaidByUsers = (totalMeanMeanPointsPaidByUsers + statsBidSale.MeanPointsPaidByUsers) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max NbBidsByBot
                if (statsBidObjectGlobal.MinNbBidsByBot > statsBidSale.NbBidsByBot)
                {
                    statsBidObjectGlobal.MinNbBidsByBot = statsBidSale.NbBidsByBot;
                }
                if (statsBidObjectGlobal.MaxNbBidsByBot < statsBidSale.NbBidsByBot)
                {
                    statsBidObjectGlobal.MaxNbBidsByBot = statsBidSale.NbBidsByBot;
                }
                Double totalMeanNbBidsByBot = statsBidObjectGlobal.MeanNbBidsByBot * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanNbBidsByBot = (totalMeanNbBidsByBot + statsBidSale.NbBidsByBot) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max NbBidsManual
                if (statsBidObjectGlobal.MinNbBidsManual > statsBidSale.NbBidsManual)
                {
                    statsBidObjectGlobal.MinNbBidsManual = statsBidSale.NbBidsManual;
                }
                if (statsBidObjectGlobal.MaxNbBidsManual < statsBidSale.NbBidsManual)
                {
                    statsBidObjectGlobal.MaxNbBidsManual = statsBidSale.NbBidsManual;
                }
                Double totalMeanNbBidsManual = statsBidObjectGlobal.MeanNbBidsManual * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanNbBidsManual = (totalMeanNbBidsManual + statsBidSale.NbBidsManual) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max NbUsersConnected
                if (statsBidObjectGlobal.MinNbUsersConnected > statsBidSale.NbUsersConnected)
                {
                    statsBidObjectGlobal.MinNbUsersConnected = statsBidSale.NbUsersConnected;
                }
                if (statsBidObjectGlobal.MaxNbUsersConnected < statsBidSale.NbUsersConnected)
                {
                    statsBidObjectGlobal.MaxNbUsersConnected = statsBidSale.NbUsersConnected;
                }
                Double totalMeanNbUsersConnected = statsBidObjectGlobal.MeanNbUsersConnected * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanNbUsersConnected = (totalMeanNbUsersConnected + statsBidSale.NbUsersConnected) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max NbUsersLogsOnThisObject
                if (statsBidObjectGlobal.MinNbUsersLogsOnThisObject > statsBidSale.NbUsersLogsOnThisSale)
                {
                    statsBidObjectGlobal.MinNbUsersLogsOnThisObject = statsBidSale.NbUsersLogsOnThisSale;
                }
                if (statsBidObjectGlobal.MaxNbUsersLogsOnThisObject < statsBidSale.NbUsersLogsOnThisSale)
                {
                    statsBidObjectGlobal.MaxNbUsersLogsOnThisObject = statsBidSale.NbUsersLogsOnThisSale;
                }
                Double totalMeanNbUsersLogsOnThisObject = statsBidObjectGlobal.MeanNbUsersLogsOnThisObject * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanNbUsersLogsOnThisObject = (totalMeanNbUsersLogsOnThisObject + statsBidSale.NbUsersLogsOnThisSale) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max SaleDurationInSeconds
                if (statsBidObjectGlobal.MinSaleDurationInSeconds > statsBidSale.SaleDurationInSeconds)
                {
                    statsBidObjectGlobal.MinSaleDurationInSeconds = statsBidSale.SaleDurationInSeconds;
                }
                if (statsBidObjectGlobal.MaxSaleDurationInSeconds < statsBidSale.SaleDurationInSeconds)
                {
                    statsBidObjectGlobal.MaxSaleDurationInSeconds = statsBidSale.SaleDurationInSeconds;
                }
                Double totalMeanSaleDurationInSeconds = statsBidObjectGlobal.MeanSaleDurationInSeconds * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanSaleDurationInSeconds = (totalMeanSaleDurationInSeconds + statsBidSale.SaleDurationInSeconds) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max WinnerNbPointsPaid
                if (statsBidObjectGlobal.MinWinnerNbPointsPaid > statsBidSale.NbPointsPaidByWinner)
                {
                    statsBidObjectGlobal.MinWinnerNbPointsPaid = statsBidSale.NbPointsPaidByWinner;
                }
                if (statsBidObjectGlobal.MaxWinnerNbPointsPaid < statsBidSale.NbPointsPaidByWinner)
                {
                    statsBidObjectGlobal.MaxWinnerNbPointsPaid = statsBidSale.NbPointsPaidByWinner;
                }
                Double totalMeanWinnerNbPointsPaid = statsBidObjectGlobal.MeanWinnerNbPointsPaid * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanWinnerNbPointsPaid = (totalMeanWinnerNbPointsPaid + statsBidSale.NbPointsPaidByWinner) / (statsBidObjectGlobal.NbSales + 1);

                //  Min Mean Max WinnerPsychologicRatio
                if (statsBidObjectGlobal.MinWinnerPsychologicRatio > statsBidSale.PsychologicRatio)
                {
                    statsBidObjectGlobal.MinWinnerPsychologicRatio = statsBidSale.PsychologicRatio;
                }
                if (statsBidObjectGlobal.MaxWinnerPsychologicRatio < statsBidSale.PsychologicRatio)
                {
                    statsBidObjectGlobal.MaxWinnerPsychologicRatio = statsBidSale.PsychologicRatio;
                }
                Double totalMeanWinnerPsychologicRatio = statsBidObjectGlobal.MeanWinnerPsychologicRatio * statsBidObjectGlobal.NbSales;
                statsBidObjectGlobal.MeanWinnerPsychologicRatio = (totalMeanWinnerPsychologicRatio + statsBidSale.PsychologicRatio) / (statsBidObjectGlobal.NbSales + 1);

                statsBidObjectGlobal.NbSales++;

                saveOrUpdate(statsBidObjectGlobal);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bidObject"></param>
        /// <returns></returns>
        public StatsBidObjectGlobal getStatsBidObjectGlobalByBidObject(BidObject bidObject)
        {
            return dao.getStatsBidObjectGlobalByIdObject(bidObject.IdBidObject);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bidLogger"></param>
        /// <returns></returns>
        public StatsBidObjectGlobal saveOrUpdate(StatsBidObjectGlobal statsBidObjectGlobal)
        {
            return dao.saveOrUpdate(statsBidObjectGlobal);
        }

    }
}
